#include <iostream>
#include <functional>
#include <string>
#include <sstream>
using namespace std;

using std::placeholders::_1;
using std::placeholders::_2;

struct Event {
    string evtName;
};
struct EventMouse : public Event {
    int posX;
    int posY;
};
class Object {
public:
    string name;

    string onCall( Event * evt, int type ) {
        stringstream ss;
        ss << "ObjectCall: " << this->name << " evtName:" << evt->evtName << " type:" << type;
        return ss.str();
    }
};

class Node : public Object {
public:
    string name;
    string state;

    string onCall( Event* evt, int type ) {
        auto evtMouse = static_cast< EventMouse*>( evt );
        stringstream ss;
        ss << "NodeCall: " << this->name << " evtName:" << evtMouse->evtName << " type:" << type << " state:" << this->state;
        return ss.str();
    }
};


string output( Object* obj, Event* evt, int type ) {
    stringstream ss;
    ss << "Call: " << obj->name << " evtName:" << evt->evtName << " type:" << type;
    return ss.str();
}


struct Listener{
    function<string( Event*, int )> func;

    Listener( ) {
    }
    Listener( function<string(Event*, int)> func ) {
        this->func = func;
    }
    template<typename Fx, typename T>
    void setFunc( Fx fn, T* obj ) {
        func = bind( fn, obj, _1, _2 );
    }
};

int main(int argc, char *argv[]) {
    Object * obj = new Object();
    Node * node = new Node();
    obj->name = "abc";
    node->name = "nodeABC";
    node->state = "nodeState";

    Event evt;
    EventMouse evtMouse;
    evtMouse.evtName = "mouseEvent";
    evt.evtName = "123";


    //Listener listener;
    //listener.func = bind( &output, obj, _1, _2 );

    //cout << listener.func( &evt, 1 ) << endl;

    //Listener listener2;
    //listener2.func = bind( &Object::onCall, obj, _1, _2 );
    //cout << listener2.func( &evt, 2 ) << endl;

    //Listener listener3;
    //listener3.func = bind( &Node::onCall, node, _1, _2 );
    //cout << listener3.func( &evtMouse, 2 ) << endl;


    //Listener listener4;
    //listener4.func = bind( &Object::onCall, node, _1, _2 );
    //cout << listener3.func( &evtMouse, 2 ) << endl;

    Listener listener5;
    listener5.setFunc( &Node::onCall, node );
    cout << listener5.func( &evtMouse, 2 ) << endl;


    cin.get();
    return 0;
}